package com.zucc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.zucc.controller.req.*;
import com.zucc.controller.resp.MenuResp;
import com.zucc.entity.*;
import com.zucc.entity.base.MyMapper;
import com.zucc.exception.SyzxException;
import com.zucc.service.MenuService;
import com.zucc.service.base.MyServiceImpl;
import com.zucc.service.base.PageData;
import com.zucc.util.MyBeanUtil;
import com.zucc.util.MyPageUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author : charspan
 * @Description :
 * @create : 2021-12-05 9:01 上午
 */
@Service
public class MenuServiceImpl extends MyServiceImpl<Menu> implements MenuService {

    @Resource
    private RoleMenuMapper roleMenuMapper;

    @Resource
    private MenuMapper menuMapper;

    @Override
    public MyMapper<Menu> mapper() {
        return menuMapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(MenuAddReq req) {
        Menu Menu = new Menu();
        BeanUtil.copyProperties(req, Menu);
        Menu.setDelFlag(0);
        Menu.setCreateTime(DateUtil.date());
        Menu.setModifyTime(DateUtil.date());
        super.saveKey(Menu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modify(MenuModifyReq req) {
        Menu menuExist = super.findById(req.getId());
        if (Objects.isNull(menuExist) || menuExist.getDelFlag().intValue() == 1) {
            throw new SyzxException("系统找不到相应编号的菜单信息");
        }
        BeanUtil.copyProperties(req, menuExist, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        menuExist.setModifyTime(DateUtil.date());
        super.updateSelective(menuExist);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOne(Long id) {
        Menu menuExist = super.findById(id);
        if (Objects.isNull(menuExist) || menuExist.getDelFlag().intValue() == 1) {
            throw new SyzxException("系统找不到相应编号的菜单信息");
        }
        menuExist.setDelFlag(1);
        menuExist.setDeleteTime(DateUtil.date());
        super.updateSelective(menuExist);
    }

    @Override
    public PageData<MenuResp> page(MenuSearchReq req) {
        Example example = new Example(Menu.class);
        example.setOrderByClause("modify_time DESC");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("delFlag", 0);

        if (StrUtil.isNotBlank(req.getRemarks())) {
            criteria.andLike("remarks", "%" + req.getRemarks() + "%");
        }
        if (Objects.nonNull(req.getSysTypeDictItemId())) {
            criteria.andEqualTo("sysTypeDictItemId", req.getSysTypeDictItemId());
        }
        if (Objects.nonNull(req.getPId()) && req.getPId().longValue()!=0L) {
            criteria.andEqualTo("pId", req.getPId());
            Menu menu = super.findById(req.getPId());
            if (Objects.isNull(menu)) {
                throw new SyzxException("此上级菜单不存在");
            }
        }
        if (StrUtil.isNotBlank(req.getName())) {
            criteria.andLike("name", "%" + req.getName() + "%");
        }

        PageData<Menu> pageData = super.findByPage(req, example);
//        PageData<MenuResp> convert = MyPageUtil.convert(pageData, MenuResp.class);

        List<Menu> fromList = pageData.getList();
        List<MenuResp> toList = new ArrayList<>();
        for (Menu menu : fromList) {
            MenuResp menuResp = new MenuResp();
            BeanUtil.copyProperties(menu, menuResp);
            toList.add(menuResp);
        }
        PageData<MenuResp> toPageData = new PageData<>();
        toPageData.setList(toList);
        toPageData.setPageNum(pageData.getPageNum());
        toPageData.setPageSize(pageData.getPageSize());
        return toPageData;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRoleMenu(RoleMenuAddReq req) {
        Example exp = new Example(RoleMenu.class);
        exp.createCriteria().andEqualTo("delFlag", 0)
                .andEqualTo("roleType", req.getRoleType());
        roleMenuMapper.deleteByExample(exp);

        List<RoleMenu> list = new ArrayList<>();
        for (Long menuId : req.getMenuIds()) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setDelFlag(0);
            roleMenu.setCreateTime(DateUtil.date());
            roleMenu.setModifyTime(DateUtil.date());
            roleMenu.setRoleType(req.getRoleType());
            roleMenu.setMenuId(menuId);
            list.add(roleMenu);
        }
        roleMenuMapper.insertList(list);
    }

    @Override
    public List<MenuResp> getMenusByRoleType(Integer roleType) {
        Example exp = new Example(RoleMenu.class);
        exp.createCriteria().andEqualTo("delFlag", 0)
                .andEqualTo("roleType", roleType);
        List<RoleMenu> roleMenus = roleMenuMapper.selectByExample(exp);
        if (Objects.isNull(roleMenus) || roleMenus.isEmpty()) {
            return new ArrayList<>();
        }
        List<Long> menuIds = roleMenus.stream().map(RoleMenu::getMenuId).collect(Collectors.toList());
        List<Menu> menus = super.findByIds(menuIds);
        List<MenuResp> resp = MyBeanUtil.converterList(menus, MenuResp.class);
        return resp;
    }

    @Override
    public JSONArray getMenuTree(MenuSearchTreeReq req) {
        Example example = new Example(Menu.class);
        example.setOrderByClause("modify_time DESC");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("delFlag", 0);

        if (Objects.nonNull(req.getSysTypeDictItemId())) {
            criteria.andEqualTo("sysTypeDictItemId", req.getSysTypeDictItemId());
        }
        Menu menu = null;
        if (Objects.nonNull(req.getPId()) && req.getPId().longValue()!=0L) {
            criteria.andEqualTo("pId", req.getPId());
            menu = super.findById(req.getPId());
            if (Objects.isNull(menu)) {
                throw new SyzxException("此根菜单点不存在");
            }
        }

        List<Menu> menuList = super.findByExample(example);
        if (Objects.nonNull(menu)) {
            menuList.add(menu);
        }

        // 构建node列表
        List<TreeNode<Long>> collect = menuList.stream().map(p -> {
            TreeNode<Long> treeNode = new TreeNode<Long>().setId(p.getId())
                    .setName(p.getName())
                    .setParentId(p.getpId())
                    .setWeight(p.getSort());
            return treeNode;
        }).collect(Collectors.toList());

        // 转换器
        List<Tree<Long>> treeList = new ArrayList<>(16);
        if (Objects.isNull(req.getPId()) || req.getPId() == 0) {
            treeList = TreeUtil.build(collect, 0L);
        } else {
            treeList = TreeUtil.build(collect, menu.getpId());
        }
//        System.out.println(JSON.toJSONString(treeList));
        return JSONArray.parseArray(JSON.toJSONString(treeList));
    }

}
